package main

import (
	"context"
	"fmt"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

/*
	@Author: ningan
	@Desc: 获取kube-system命名空间下的Pod列表
*/

func main() {
	/*
		1. k8s的配置文件
		2. 保证开发机能通过这个配置文件连接到k8s集群
	*/

	// 1. 加载配置文件，生成config对象
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		panic(err)
		// panic(err.Error())
	}

	// 2. 配置API路径  请求的HTTP路径
	config.APIPath = "api" // pods,  /api/v1/pods
	// config.APIPath = "apis" // deployments,  /apis/apps/v1/namespaces/{namespace}/deployments/{deployment}

	// 3. 配置请求的资源组/资源版本 GV
	config.GroupVersion = &corev1.SchemeGroupVersion // 无名资源组, group: " ", version: "v1"

	// 4. 配置数据的编解码工具  序列化和反序列化
	config.NegotiatedSerializer = scheme.Codecs

	// 5. 通过kubeconfg配置信息实例化RESTClient对象
	restClient, err := rest.RESTClientFor(config)
	if err != nil {
		panic(err)
	}

	// 6. 定义接收返回值的变量
	result := &corev1.PodList{}

	// 跟APIServer交互
	err = restClient.
		Get().                                                                  // RESTClient对象构建HTTP请求参数  请求方法：Get、Post、Put、Delete、Patch
		Namespace("kube-system").                                               // 命名空间
		Resource("pods").                                                       // 资源名
		VersionedParams(&metav1.ListOptions{Limit: 50}, scheme.ParameterCodec). // 将一些查询选项(如limit、TimeoutSeconds)添加到请求参数中 limit参数表示最多检索出多少信息
		Do(context.TODO()).                                                     // 执行该请求
		Into(result)                                                            // 将kube-apiserver返回的结果（Result对象）解析到corev1.PodList对象中
	if err != nil {
		panic(err)
	}

	/*
		1）Get定义请求方式，返回了一个Request结构体对象。这个Request结构体对象，就是构建访问APIServer用的。
		2）依次执行了Namespace、Resource、VersionedParams，构建与APIServer交互的参数。
		3）Do方法通过requets发起请求，然后通过transformResponse解析请求返回，并绑定到对应资源对象的结构体对象上。这里的话，表示的是corev1.PodList对象。
		4）request先是检查了有没有可用的client，在这里开始调用net/http包的功能。
	*/

	/*
		1) RESTClient发送请求的过程对Go语言标准库net/http进行了封装，由Do -> Request函数实现。
		2) 请求发送之前需要根据请求参数生成请求的RESTful URL，由r.URL().String()函数完成。 http://xxxx:x/api/v1/namespaces/kube-system/pods?limit=1
		3) 通过Go语言标准库net/http向RESTful URL(即kube-apiserver)发送请求，请求得到的结果存放在http.Response的Body对象中，fn函数（即transformResponse）将结果转化为资源对象。
	*/

	// 格式化输出结果
	for _, item := range result.Items {
		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
	}
}

